package com.darwin.darwinUI.manager
{
	import com.darwin.darwinBitmapEngine.core.ContainerNode;
	import com.darwin.darwinBitmapEngine.core.INode;
	import com.darwin.darwinBitmapEngine.core.Node;
	import com.darwin.darwinBitmapEngine.events.NodeEvent;
	import com.darwin.darwinUI.manager.base.IToolTip;
	import com.darwin.darwinUI.manager.base.TipsHideTween;
	import com.darwin.darwinUI.manager.base.TipsShowTween;
	import com.darwin.darwinUI.manager.base.ToolTipBase;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;
	import flash.utils.setTimeout;
	
	/**
	 * TIPS管理器
	 * @author lipi
	 */
	public class ToolTipManager extends EventDispatcher
	{
//		public static const ITEM_OVER:String = "itemOver";
//		public static const ITEM_CLICK:String = "itemClick";
//		public static const ITEM_UP:String = "itemUp";
		public static const ITEM_OUT:String = "itemOut";//当鼠标移开项是消失
		public static const STAGE_CLICK:String = "stageClick";//当单击的是舞台时消失
		public static const OUT_CLICK:String = "outClick";//当单击的不是项或tips时消失
		public static const ALL_OUT:String = "allOut";//当同时移开项和tips消失
		public static const PASSIVE:String = "passive";//被动的。PASSIVE模式需要手动调用hideTips关闭
		
		
		public static const DOWN:String = "down";
		public static const UP:String = "up";
		public static const LEFT:String = "left";
		public static const RIGHT:String = "right";
		public static const FOLLOW:String = "follow";
		
		
		public function ToolTipManager(target:IEventDispatcher=null)
		{
			super(target);
			_tooltipDic = new Dictionary();
			_displayDic = new Dictionary();
			_hideTypeDic = new Dictionary();
			_hideTweenDic = new Dictionary();
			_directionDic = new Dictionary();
			_showTweenDic = new Dictionary();
			
			_offsetX = new Dictionary();
			_offsetY = new Dictionary();
			
			_stage = UIStage.uiStage;
			_stage.addEventListener(Event.RESIZE,stageResizeHandler);
			_stage.addEventListener(MouseEvent.CLICK,stageClickHandler,true);
			_stage.addEventListener(MouseEvent.MOUSE_MOVE,moveHandler);
			
		}
		
		private function moveHandler(event:MouseEvent):void
		{
			for(var key:Object in _showTweenDic)
			{
				if(_directionDic[key] == ToolTipManager.FOLLOW)
				{
					var $showTween:TipsShowTween = _showTweenDic[key];
					if($showTween == null)
					{
						$showTween = this.showTween;
					}
					$showTween.reset(key,_displayDic[key],_directionDic[key],this.parent);
				}
			}
		}
		
		private var _stage:Stage;
		
		
		/**
		 * 窗口大小改变时处理 
		 */
		private function stageResizeHandler(e:Event):void
		{
			resizeHandler(_stage.stageWidth,_stage.stageHeight);
		}
		
		protected function resizeHandler(stageWidth:Number,stageHeight:Number):void
		{
			for(var key:Object in _showTweenDic)
			{
				var $showTween:TipsShowTween = _showTweenDic[key];
				if($showTween == null)
				{
					$showTween = this.showTween;
				}
				
				$showTween.reset(key,_displayDic[key],_directionDic[key],this.parent);
			}
		}
		
		
		private var _tooltipDic:Dictionary;
		private var _displayDic:Dictionary;
		private var _hideTypeDic:Dictionary;
		private var _hideTweenDic:Dictionary;
		private var _directionDic:Dictionary;
		private var _showTweenDic:Dictionary;
		
		private var _offsetX:Dictionary;
		private var _offsetY:Dictionary;
		
		
		/**
		 * 显示一tips。如果当前面有个tips还在显示中，如果新传入的tooltip和之前的一样，
		 * 则新tips无效，如果不一样则把之前的关闭
		 * @param tooltip tips项，可以是显示对象实例，显示对象类，或已注册的字符串
		 * @param item 调用tips的对象,可以是显示对象(Sprite)或场景物件(Node || ContainerNode)
		 * @param direction 方向
		 * @param hideType 标记TIPS怎么情况下隐藏
		 * @param showTween 负责显示的类
		 */
		public function showTips(tooltip:*,item:*,tipsData:Object = null,
								 direction:String = ToolTipManager.UP,hideType:String = ToolTipManager.ITEM_OUT,
								 showTween:TipsShowTween = null,hideTween:TipsHideTween = null,offsetX:Number = 0,offsetY:Number = 0):void
		{
			if(tooltip == null) tooltip = defaultToolTip;//如果tooltip为null则显示默认类
			
			if(_tooltipDic[item] != null)
			{
				if(_tooltipDic[item] == tooltip)
				{
					return;
				}else{
					hideTips(item);
				}
			}
			
			_tooltipDic[item] = tooltip;
			
			var $tooltip:IToolTip;
			var $tooltipDisplay:DisplayObject;
			if(tooltip is DisplayObject)
			{
				$tooltipDisplay = tooltip as DisplayObject;
			}else if(tooltip is Class){
				$tooltipDisplay = new tooltip() as DisplayObject;
			}else if(tooltip is String){
				var $tooltipClass:Class = _toolTipList[tooltip];
				$tooltipDisplay = new $tooltipClass() as DisplayObject;
			}
			$tooltip = $tooltipDisplay as IToolTip;
			
			_displayDic[item] = $tooltipDisplay;
			_hideTypeDic[item] = hideType;
			_hideTweenDic[item] = hideTween;
			_directionDic[item] = direction;
			_showTweenDic[item] = showTween;
			
			_offsetX[item] = offsetX;
			_offsetY[item] = offsetY;
			
			var $tween:TipsShowTween = showTween;
			if($tween == null)
			{
				$tween = this.showTween;
			}
			
			if($tooltip != null) $tooltip.setData(tipsData,item);//设置数据
			
			addItemEvent(item);
			addDisplayEvent($tooltipDisplay);
			
			$tween.start(item,$tooltipDisplay,direction,parent,offsetX,offsetY);
			$tween.tween(item,$tooltipDisplay,direction,parent,offsetX,offsetY);
		}
		
		
		
		
		public function hideTips(item:*):void
		{
			removeItemEvent(item);
			removeDisplayEvent(_displayDic[item] as DisplayObject);
			
			
			var $tween:TipsHideTween = _hideTweenDic[item] as TipsHideTween;
			if($tween == null)
			{
				$tween = this.hideTween;
			}
			$tween.start(item,_displayDic[item],_directionDic[item],this.parent);
			$tween.tween(item,_displayDic[item],_directionDic[item],this.parent);
			
			delete _tooltipDic[item];
			delete _displayDic[item];
			delete _hideTypeDic[item];
			delete _hideTweenDic[item];
			delete _directionDic[item];
			delete _showTweenDic[item];
			
			delete _offsetX[item];
			delete _offsetY[item];
			
			delete _stageClickList[item];
			delete _allOutList[item];
		}
		
		/**
		 *	隐藏所有tips 
		 */
		public function hideAllTips():void
		{
			for(var item:* in _tooltipDic) 
			{
				hideTips(item);
			}
		}
		
		/**
		 *	隐藏HideType为某一类的tips 
		 * @param hideType
		 * 
		 */
		public function hideTipsByHideType(hideType:String):void
		{
			for(var item:* in _hideTypeDic) 
			{
				if(_hideTypeDic[item] == hideType)
				{
					hideTips(item);
				}
			}
		}
		
		
		private function addItemEvent(item:*):void
		{
			if(item is DisplayObject)
			{
				var $displayItem:DisplayObject = item as DisplayObject;
				$displayItem.addEventListener(MouseEvent.ROLL_OUT,mouseHandler);
				$displayItem.addEventListener(MouseEvent.CLICK,mouseHandler);
				$displayItem.addEventListener(MouseEvent.ROLL_OVER,mouseHandler);
			}else if(item is INode)
			{
				var $nodeItem:EventDispatcher = item as EventDispatcher;
				$nodeItem.addEventListener(NodeEvent.MOUSE_OUT,mouseHandler);
				$nodeItem.addEventListener(NodeEvent.MOUSE_CLICK,mouseHandler);
				$nodeItem.addEventListener(NodeEvent.MOUSE_OVER,mouseHandler);
			}

		}
		
		
		private function removeItemEvent(item:*):void
		{
			if(item is Sprite)
			{
				var $spriteItem:Sprite = item as Sprite;
				$spriteItem.removeEventListener(MouseEvent.ROLL_OUT,mouseHandler);
				$spriteItem.removeEventListener(MouseEvent.CLICK,mouseHandler);
				$spriteItem.removeEventListener(MouseEvent.ROLL_OVER,mouseHandler);
			}else if(item is INode)
			{
				var $nodeItem:EventDispatcher = item as EventDispatcher;
				$nodeItem.removeEventListener(NodeEvent.MOUSE_OUT,mouseHandler);
				$nodeItem.removeEventListener(NodeEvent.MOUSE_CLICK,mouseHandler);
				$nodeItem.removeEventListener(NodeEvent.MOUSE_OVER,mouseHandler);
			}
		}
		
		
		
		private function addDisplayEvent(display:DisplayObject):void
		{
			if(display is Sprite)
			{
				(display as Sprite).addEventListener(MouseEvent.CLICK,dMouseHandler);
				(display as Sprite).addEventListener(MouseEvent.ROLL_OVER,dMouseHandler);
				(display as Sprite).addEventListener(MouseEvent.ROLL_OUT,dMouseHandler);
			}
		}
		
		private function removeDisplayEvent(display:DisplayObject):void
		{
			if(display is Sprite)
			{
				(display as Sprite).removeEventListener(MouseEvent.CLICK,dMouseHandler);
				(display as Sprite).removeEventListener(MouseEvent.ROLL_OVER,dMouseHandler);
				(display as Sprite).removeEventListener(MouseEvent.ROLL_OUT,dMouseHandler);
			}
		}
		
		
		//鼠标处理
		private function mouseHandler(e:Event):void
		{
			switch(e.type)
			{
				case MouseEvent.CLICK:
				case NodeEvent.MOUSE_CLICK:
					onClick(e.currentTarget);
					break;
				case MouseEvent.ROLL_OUT:
				case NodeEvent.MOUSE_OUT:
					onRollOut(e.currentTarget);
					break;
				case MouseEvent.ROLL_OVER:
				case NodeEvent.MOUSE_OVER:
					onRollOver(e.currentTarget);
					break;
			}
		}
		
		//鼠标处理
		private function dMouseHandler(e:MouseEvent):void
		{
			switch(e.type)
			{
				case MouseEvent.CLICK:
					onClickD(e.currentTarget);
					break;
				case MouseEvent.ROLL_OVER:
					onRollOverD(e.currentTarget);
					break;
				case MouseEvent.ROLL_OUT:
					onRollOutD(e.currentTarget);
					break;
			}
		}
		
		private var _stageClickList:Dictionary = new Dictionary();
		private var _allOutList:Dictionary = new Dictionary();
		
		
		/**
		 * 舞台被单击时处理。对于被设置为OUT_CLICK时消失的tips,实际是会延迟消失的，
		 * 程序会判断是否单击的是TIPS或触发鼠标的物件
		 * 
		 * STAGE_CLICK被设成STAGE_CLICK会立即关闭
		 */
		private function stageClickHandler(e:MouseEvent):void
		{
			var $b:Boolean = false;
			for(var key:Object in _hideTypeDic)
			{
				if(_hideTypeDic[key] == ToolTipManager.OUT_CLICK)
				{
					_stageClickList[key] = key;
					$b = true;
				}
				if(_hideTypeDic[key] == ToolTipManager.STAGE_CLICK)
				{
					hideTips(key);
				}
			}
			if($b)
			{
				setTimeout(exeStageClick,50);
			}
		}
		
		/**
		 * 执行舞台单击。
		 */
		private function exeStageClick():void
		{
			for(var key:Object in _stageClickList)
			{
				hideTips(key);
			}
		}
		
		
		//项单击处理。项单击会阻止标记为outClick的tips被移除
		private function onClick(item:*):void
		{
			delete _stageClickList[item];
		}
		
		private function onRollOut(item:*):void
		{
			if(_hideTypeDic[item] == ToolTipManager.ITEM_OUT)
			{
				hideTips(item);
			}
			else if(_hideTypeDic[item] == ToolTipManager.ALL_OUT){
				_allOutList[item] = item;
				setTimeout(exeRollOut,500);
			}
		}
		
		private function exeRollOut():void
		{
			for(var key:Object in _allOutList)
			{
				hideTips(key);
			}
		}
		
		
		/**
		 * 鼠标移开阻止标记为allOut的tips被移除
		 */
		private function onRollOver(item:*):void
		{
			delete _allOutList[item];
		}		
		
		
		
	/////////////////////////////////////////////////////////////////////////
		
		
		
		/**
		 * 显示对象单击会阻止标记为outClick的tips被移除
		 */
		private function onClickD(display:*):void
		{
			for(var key:Object in _displayDic)
			{
				if(display == _displayDic[key])
				{
					delete _stageClickList[key];
				}
			}
		}
		
		/**
		 * 鼠标移出处理tips操作
		 */
		private function onRollOutD(display:*):void
		{
			for(var key:Object in _displayDic)
			{
				if(display == _displayDic[key])
				{
					onRollOut(key);
				}
			}
		}
		
		
		
		/**
		 * 鼠标移开阻止标记为allOut的tips被移除
		 */
		private function onRollOverD(display:*):void
		{
			for(var key:Object in _displayDic)
			{
				if(display == _displayDic[key])
				{
					delete _allOutList[key];
				}
			}
		}
		
		
		
		
		
		
//		///////////////////////////////////////////////////
		
		
		private var _toolTipList:Object = {};
		
		/**
		 * 注册一个提示类
		 * @param aClass 类
		 * @param toolTipType 对应别名
		 * 
		 */
		public function registerToolTip(aClass:Class,toolTipType:String = "simple"):void
		{
			_toolTipList[toolTipType] = aClass;
		}
		
		
		
		private var _parent:DisplayObjectContainer;
		
		/**
		 * 弹出对象所在的父容器，如果未设置过parent，默认使用stage
		 */
		public function get parent():DisplayObjectContainer
		{
			if(_parent)
			{
				return _parent;
			}
			if(UIManager.getPopUpManager().parent != null && UIManager.getPopUpManager().parent.numChildren > 0)
			{
				return popupTipsParent || _stage;
			}else{
				return sceneTipsParent || _stage;
			}
		}
		
		public function set parent(value:DisplayObjectContainer):void
		{
			_parent = value;
		}
		
		
		
		private var _sceneTipsParent:DisplayObjectContainer;

		public function get sceneTipsParent():DisplayObjectContainer
		{
			return _sceneTipsParent;
		}

		public function set sceneTipsParent(value:DisplayObjectContainer):void
		{
			_sceneTipsParent = value;
		}
		
		
		
		private var _popupTipsParent:DisplayObjectContainer;

		public function get popupTipsParent():DisplayObjectContainer
		{
			return _popupTipsParent;
		}

		public function set popupTipsParent(value:DisplayObjectContainer):void
		{
			_popupTipsParent = value;
		}
		
		
		
		private var _showTween:TipsShowTween;

		/**
		 * 显示tips过程
		 */
		public function get showTween():TipsShowTween
		{
			if(_showTween == null)
			{
				_showTween = new TipsShowTween();
			}
			return _showTween;
		}

		public function set showTween(value:TipsShowTween):void
		{
			_showTween = value;
		}
		
		
		private var _hideTween:TipsHideTween;

		/**
		 * 隐藏Tips过程
		 */
		public function get hideTween():TipsHideTween
		{
			if(_hideTween == null)
			{
				_hideTween = new TipsHideTween();
			}
			return _hideTween;
		}

		public function set hideTween(value:TipsHideTween):void
		{
			_hideTween = value;
		}
		
		
		private var _defaultToolTip:Class = ToolTipBase;
		
		/**
		 * 默认的使用的tips类
		 */
		public function get defaultToolTip():Class
		{
			return _defaultToolTip;
		}
		
		public function set defaultToolTip(value:Class):void
		{
			_defaultToolTip = value;
		}
		
		
		
	}
}